<script setup lang="tsx">
import 'echarts-wordcloud'
import {
  computed,
  onActivated,
  onBeforeUnmount,
  onMounted,
  onUnmounted,
  ref,
  unref,
  watch,
} from 'vue'
import { useMutationObserver } from '@vueuse/core'
import { IsUtils, propTypes } from '@sat/shared-utils'
import { debounce } from 'lodash-es'
import * as echarts from 'echarts'
import { useDesign } from '@sat/shared-hooks'
import type { EChartsOption } from 'echarts'
import type { PropType } from 'vue'

const props = defineProps({
  options: {
    type: Object as PropType<EChartsOption>,
    required: true,
  },
  width: propTypes.oneOfType([Number, String]).def(''),
  height: propTypes.oneOfType([Number, String]).def('50vh'),
})
const { getPrefixCls } = useDesign()
const prefixCls = getPrefixCls('echart')

// 切换明暗主题
const isDark = ref(false)
// 监听html的class变化
function watchHtmlClassList(callback: MutationCallback) {
  return useMutationObserver(document.documentElement, callback, {
    attributes: true,
    attributeFilter: ['class'],
  })
}
// 监听外部暗黑模式做出相关改变

const htmlObserver = watchHtmlClassList((mutations) => {
  const htmlClassList = (mutations[0].target as HTMLElement).classList
  if (htmlClassList.contains('dark'))
    isDark.value = true
  else
    isDark.value = false
})

onUnmounted(() => {
  htmlObserver?.stop()
})

const theme = computed(() => {
  const echartTheme: boolean | string = unref(isDark) ? true : 'auto'

  return echartTheme
})

const options = computed(() => {
  return Object.assign(props.options, {
    darkMode: unref(theme),
  })
})

const elRef = ref<ElRef>()
let echartRef: Nullable<echarts.ECharts> = null

const contentEl = ref<Element>()

const styles = computed(() => {
  const width = IsUtils.isString(props.width) ? props.width : `${props.width}px`
  const height = IsUtils.isString(props.height)
    ? props.height
    : `${props.height}px`

  return {
    width,
    height,
  }
})

function initChart() {
  if (unref(elRef) && props.options) {
    echartRef = echarts.init(unref(elRef) as HTMLElement)
    echartRef?.setOption(unref(options))
  }
}

watch(
  () => options.value,
  (options) => {
    if (echartRef) {
      // 绘制不同图标之前需要清除，否则会出现不同类型统计图重复绘制的情况
      echartRef.clear()

      echartRef?.setOption(options)
    }
  },
  {
    deep: true,
  },
)

const resizeHandler = debounce(() => {
  if (echartRef)
    echartRef.resize()
}, 100)

async function contentResizeHandler(e: Event) {
  if ((e as TransitionEvent).propertyName === 'width')
    resizeHandler()
}

onMounted(() => {
  initChart()
  window.addEventListener('resize', resizeHandler)
})

onBeforeUnmount(() => {
  window.removeEventListener('resize', resizeHandler)
  unref(contentEl)
  && (unref(contentEl) as Element).removeEventListener(
    'transitionend',
    contentResizeHandler,
  )
})

onActivated(() => {
  if (echartRef)
    echartRef.resize()
})
</script>

<template>
  <div ref="elRef" :class="[$attrs.class, prefixCls]" :style="styles" />
</template>
